package asteroids.model;

import be.kuleuven.cs.som.annotate.*;

/**
 * @version	1.0
 * @author 	Jomi Verwimp
 */
public class Bullet extends GameObject {

	/**
	 * @param 	xPos
	 * @param 	yPos
	 * @param 	xVel
	 * @param 	yVel
	 * @param 	radius
	 * @param 	source
	 * @param 	world
	 * 
	 * @effect	| super(xPos, yPos, xVel, yVel, radius, (4/3)*Math.PI*Math.pow(radius,3)*7.8E12)
	 * @effect	| setWorld(world)
	 * 
	 * @post	| new.getSource() == source
	 */
	public Bullet(double xPos, double yPos, double xVel, double yVel, double radius, Ship source, World world) {
		super(xPos, yPos, xVel, yVel, radius, (4/3)*Math.PI*Math.pow(radius,3)*7.8E12);
		
		this.setWorld(world);
		
		if (source == null)
			throw new IllegalArgumentException("A bullets source cannot be null");
		this.source = source;
	}
	
	/**
	 * @return	| result == this.source;
	 */
	@Basic
	public Ship getSource() {
		return this.source;
	}
	
	private final Ship source;
	
	/**
	 * @return	| result == this.bounced
	 */
	@Basic
	public boolean hasBounced() {
		return this.bounced;
	}

	/**
	 * @param 	bounce
	 * @post	| new.hasBounced() == true
	 */
	public void bounce() {
		this.bounced = true;
	}
	
	private boolean bounced = false;
	
	/**
	 * @effect	| if (hasBounced())
	 * 			|	then (terminate())
	 * 			| else bounce()
	 */
	public void checkBounced() {
		if(hasBounced() == true) {
			terminate();
		} else {
			bounce();
		}
	}
	
	/**
	 * @effect	| if (hasBounced())
	 * 			|	then terminate()
	 * 			| else {
	 * 			|	bounce()
	 * 			|	Vector newVel = new Vector(-getVelocity().getX(), getVelocity().getY())
     *			|	setVelocity(newVel)
	 */
	@Override
	public void bounceVerBound() {
		if(hasBounced()) {
			terminate();
		} else {
			bounce();
			super.bounceVerBound();
		}
	}
	
	/**
	 * @effect	| if (hasBounced())
	 * 			|	then terminate()
	 * 			| else {
	 * 			|	bounce()
	 * 			|	Vector newVel = new Vector(getVelocity().getX(), -getVelocity().getY())
     *			|	setVelocity(newVel)
	 */
	@Override
	public void bounceHorBound() {
		if(hasBounced()) {
			terminate();
		} else {
			bounce();
			super.bounceHorBound();
		}
	}
	
	/**
	 * @effect	| getSource().removeBullet(this)
     *			| setSource(null)
     *			| setWorld(null)
	 */
	public void terminate() {
		getSource().removeBullet(this);
		setWorld(null);
	}

	/**
	 * @param	other
	 * @effect	| other.resolve(this)
	 */
	@Override
	public void collide(WorldObject other) {
		other.resolve(this);
	}

	/**
	 * @param	other
	 * @effect	| if(getSource() != other)
	 * 			|	then(other.terminate())
	 * 			|	else(this.terminate())
	 */
	@Override
	public void resolve(Ship other) {
		if(getSource() != other) {
			other.terminate();
		}
		this.terminate();
	}

	/**
	 * @param	other
	 * @effect	| this.terminate()
	 * @effect	| other.terminate()
	 */
	@Override
	public void resolve(Asteroid other) {
		this.terminate();
		other.terminate();
	}

	/**
	 * @param	other
	 * @effect	| this.terminate()
	 * @effect	| other.terminate()
	 */
	@Override
	public void resolve(Bullet other) {
		this.terminate();
		other.terminate();
	}

	/**
	 * @param	hb
	 * @effect	| bounceHorBound()
	 */
	@Override
	public void resolve(HorBound hb) {
		bounceHorBound();
	}

	/**
	 * @param	vb
	 * @effect	| bounceVerBound()
	 */
	@Override
	public void resolve(VerBound vb) {
		bounceVerBound();
	}

}